package com.comprehensive.personalfile.service.impl;

import com.comprehensive.common.dto.FolderFlieInfo;
import com.comprehensive.common.dto.PageResponse;
import com.comprehensive.common.enumType.StorageEnum;
import com.comprehensive.common.po.FileInfo;
import com.comprehensive.personalfile.feign.FileInfoFeignClient;
import com.comprehensive.personalfile.service.FileService;
import com.comprehensive.personalfile.util.IpUtil;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.libtorrent4j.*;
import org.libtorrent4j.alerts.AddTorrentAlert;
import org.libtorrent4j.alerts.Alert;
import org.libtorrent4j.alerts.AlertType;
import org.libtorrent4j.alerts.BlockFinishedAlert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

@Service
public class FileServiceImpl implements FileService {

    @Autowired
    private FileInfoFeignClient fileInfoFeignClient;

    @Value("${upload.path}")
    private String uploadPath;

    private HashMap<String,byte[]> magentDataByte=new HashMap<>();

    @Override
    public PageResponse<FileInfo> listPage(int pageNum, int pageSize) {
        // 调用文件信息服务的分页查询方法
        return fileInfoFeignClient.listPage(pageNum, pageSize);
    }

    @Override
    public FileInfo uploadFile(MultipartFile file) throws IOException {
        if (file.isEmpty()) {
            throw new IllegalArgumentException("上传文件不能为空");
        }

        // 生成唯一文件ID
        String fileId = UUID.randomUUID().toString();
        // 获取原始文件名和扩展名
        String originalFileName = file.getOriginalFilename();
        String fileType = originalFileName.substring(originalFileName.lastIndexOf(".") + 1);
        String fileName = fileId + "." + fileType;

        // 创建上传目录（如果不存在）
        File uploadDir = new File(uploadPath);
        if (!uploadDir.exists()) {
            uploadDir.mkdirs();
        }

        // 保存文件到本地
        File destFile = new File(uploadPath + File.separator + fileName);
        file.transferTo(destFile);

        // 构建文件信息
        FileInfo fileInfo = new FileInfo();
        fileInfo.setFileName(fileName);
        fileInfo.setOriginalFileName(originalFileName);
        fileInfo.setContentType(fileType);
        fileInfo.setFileSize(file.getSize());
        fileInfo.setFilePath(destFile.getAbsolutePath());
        fileInfo.setStorageType(StorageEnum.LOCAL.getCode());
        fileInfo.setFileUrl(IpUtil.getLocalIp()+":8080/file/download/" + fileId);


        boolean saveResult = fileInfoFeignClient.saveFileInfo(fileInfo);

        return fileInfo;
    }

    @Override
    public void downloadFile(String fileId, HttpServletResponse response) throws IOException {
        // 在实际应用中，应该从数据库查询文件信息
        // 这里简化处理，假设文件名格式为 {fileId}.{fileType}
        // 遍历上传目录查找匹配的文件
        File uploadDir = new File(uploadPath);
        File[] files = uploadDir.listFiles((dir, name) -> name.startsWith(fileId + "."));

        if (files == null || files.length == 0) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, "文件不存在");
            return;
        }

        File file = files[0];
        String originalFileName = "download." + file.getName().substring(fileId.length() + 1);

        // 设置响应头
        response.setContentType("application/octet-stream");
        response.setContentLengthLong(file.length());
        response.setHeader("Content-Disposition", "attachment; filename=\"" + originalFileName + "\"");

        // 写入响应流
        try (InputStream in = new FileInputStream(file);
             OutputStream out = response.getOutputStream()) {
            byte[] buffer = new byte[1024 * 8];
            int len;
            while ((len = in.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            out.flush();
        }

    }

    @Override
    public List<FolderFlieInfo> listFiles(String directoryPath) throws IOException {
        File directory = new File(directoryPath);
        if (!directory.exists()) {
            throw new FileNotFoundException("目录不存在: " + directoryPath);
        }
        if (!directory.isDirectory()) {
            throw new IllegalArgumentException("路径不是目录: " + directoryPath);
        }
        return buildFolderFlieInfoList(directory);
    }

    /**
     * 构建文件夹文件信息列表
     * @param directory
     * @return
     */
    private List<FolderFlieInfo> buildFolderFlieInfoList(File directory) {
        List<FolderFlieInfo> folderFlieInfoList = new ArrayList<>();
        File[] files = directory.listFiles();
        if (files == null) {
            return folderFlieInfoList;
        }
        for (File file : files) {
            FolderFlieInfo folderFlieInfo = new FolderFlieInfo();
            if (file.getName().startsWith(".")) {
                continue;
            }
            folderFlieInfo.setName(file.getName());
            folderFlieInfo.setPath(file.getAbsolutePath());
            if (file.isDirectory()) {
                folderFlieInfo.setFile(false);
                //递归处理子目录
                folderFlieInfo.setChildren(buildFolderFlieInfoList(file));
            }else {
                folderFlieInfo.setFile(true);
                folderFlieInfo.setChildren(null);
            }
            folderFlieInfoList.add(folderFlieInfo);
        }
        return folderFlieInfoList;
    }

    @Override
    public InputStream readFileAsStream(String filePath) throws IOException {
        File file = new File(filePath);
        if (!file.exists()) {
            throw new FileNotFoundException("文件不存在: " + filePath);
        }
        if (!file.isFile()) {
            throw new IllegalArgumentException("路径不是文件: " + filePath);
        }
        return new FileInputStream(file);
    }

    @Override
    public FileInfo uploadChunk(String uploadId, int chunkIndex, int totalChunks, String fileName, MultipartFile chunkFile) throws IOException {
        // 创建临时分片目录
        String tempChunkDir = uploadPath + File.separator + "temp" + File.separator + uploadId;
        File chunkDir = new File(tempChunkDir);
        if (!chunkDir.exists()) {
            chunkDir.mkdirs();
        }

        // 保存分片文件
        String chunkFileName = chunkIndex + ".part";
        File destChunkFile = new File(tempChunkDir + File.separator + chunkFileName);
        chunkFile.transferTo(destChunkFile);

        // 返回分片信息
        FileInfo fileInfo = new FileInfo();
        fileInfo.setId(Long.valueOf(uploadId));
        fileInfo.setFileName(fileName);
        fileInfo.setOriginalFileName(fileName);
        fileInfo.setContentType(fileName.substring(fileName.lastIndexOf(".") + 1));
        fileInfo.setFileSize(chunkFile.getSize());
        fileInfo.setFilePath(destChunkFile.getAbsolutePath());


        return fileInfo;
    }

    @Override
    public List<Integer> getUploadedChunks(String uploadId, String fileName) throws IOException {
        // 临时分片目录
        String tempChunkDir = uploadPath + File.separator + "temp" + File.separator + uploadId;
        File chunkDir = new File(tempChunkDir);

        if (!chunkDir.exists()) {
            return new ArrayList<>();
        }

        // 获取所有已上传的分片文件
        File[] chunkFiles = chunkDir.listFiles((dir, name) -> name.endsWith(".part"));
        if (chunkFiles == null || chunkFiles.length == 0) {
            return new ArrayList<>();
        }

        // 解析分片索引
        List<Integer> uploadedIndices = new ArrayList<>();
        for (File file : chunkFiles) {
            String chunkFileName = file.getName();
            String indexStr = chunkFileName.replace(".part", "");
            uploadedIndices.add(Integer.parseInt(indexStr));
        }

        // 排序并返回
        Collections.sort(uploadedIndices);
        return uploadedIndices;
    }

    @Override
    public FileInfo mergeChunks(String uploadId, String fileName) throws IOException {
        // 临时分片目录
        String tempChunkDir = uploadPath + File.separator + "temp" + File.separator + uploadId;
        File chunkDir = new File(tempChunkDir);

        if (!chunkDir.exists()) {
            throw new FileNotFoundException("分片目录不存在: " + tempChunkDir);
        }

        // 获取所有分片文件并按索引排序
        File[] chunkFiles = chunkDir.listFiles((dir, name) -> name.endsWith(".part"));
        if (chunkFiles == null || chunkFiles.length == 0) {
            throw new FileNotFoundException("未找到分片文件: " + tempChunkDir);
        }

        List<File> sortedChunks = Arrays.stream(chunkFiles)
                .sorted(Comparator.comparingInt(f -> Integer.parseInt(f.getName().replace(".part", ""))))
                .collect(Collectors.toList());

        // 创建最终文件
        String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);
        String finalFileName = UUID.randomUUID().toString() + "." + fileType;
        File finalFile = new File(uploadPath + File.separator + finalFileName);

        // 合并分片文件
        try (FileOutputStream outputStream = new FileOutputStream(finalFile)) {
            byte[] buffer = new byte[1024 * 1024]; // 1MB缓冲区
            for (File chunk : sortedChunks) {
                try (FileInputStream inputStream = new FileInputStream(chunk)) {
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    }
                }
                chunk.delete(); // 删除已合并的分片
            }
        }

        // 删除临时目录
        chunkDir.delete();

        // 构建文件信息
        FileInfo fileInfo = new FileInfo();
        fileInfo.setFileName(finalFileName);
        fileInfo.setOriginalFileName(fileName);
        fileInfo.setContentType(fileType);
        fileInfo.setFileSize(finalFile.length());
        fileInfo.setFilePath(finalFile.getAbsolutePath());


        boolean saveResult = fileInfoFeignClient.saveFileInfo(fileInfo);

        return fileInfo;
    }
    @Override
    public String getMarkdownContent(String filePath) throws IOException {
        Path path = Path.of(filePath);
        if (!Files.exists(path)) {
            throw new FileNotFoundException("文件不存在: " + filePath);
        }
        if (!filePath.endsWith(".md")) {
            return "文件类型不支持";
        }
        return Files.readString(path);
    }

    @Override
    public void saveMarkdownContent(String filePath, String content) throws IOException {
        Path path = Path.of(filePath);
        Files.writeString(path, content, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
    }
    @Override
    public Map<String,Object> getMagnetLinkInfoByUrl(String magnetLink) {
        Map<String,Object> resultMap = new HashMap<>();
        resultMap.put("magnetLink", magnetLink);
        resultMap.put("name", "");
        resultMap.put("fileList", null);
        resultMap.put("status",false);
        byte[] data=null;
        if (!magentDataByte.containsKey(magnetLink)) {

            if (StringUtils.isBlank(uploadPath)) {
                return resultMap;
            }
            // 解析磁力链接
            String savePath = uploadPath + File.separator + "magnet";
            File magnetFilePat = new File(savePath);
            if (!magnetFilePat.exists()) {
                magnetFilePat.mkdirs();
            }
            SessionManager sessionManager = new SessionManager();
            sessionManager.start();
            data = sessionManager.fetchMagnet(magnetLink, 30, magnetFilePat);
            if (data == null) {
                return resultMap;
            }
            magentDataByte.put(magnetLink, data);
            sessionManager.stop();
        }else {
            data = magentDataByte.get(magnetLink);
        }
        TorrentInfo ti = TorrentInfo.bdecode(data);
        resultMap.put("status",true);
        resultMap.put("name", ti.name());
        FileStorage files = ti.files();
        List<FileInfo>fileInfos = new ArrayList<>();
        for (int i=0;i<files.numFiles();i++) {
            FileInfo fileInfo = new FileInfo();
            fileInfo.setFileName(files.fileName(i));
            fileInfo.setFileSize(files.fileSize(i));
            fileInfo.setFilePath(files.filePath(i));
            System.out.println("file: " + files.fileName(i)+"fileSize: "+files.fileSize(i));
            fileInfos.add(fileInfo);
        }
        resultMap.put("fileList",fileInfos);
        return resultMap;
    }

    public void downloadMagnetLink(String magnetLink,int selectDownloadIndex) throws InterruptedException {
        if (uploadPath == null) {
            return;
        }
        // 解析磁力链接
        String savePath=uploadPath+File.separator+"magnet";
        File magnetFilePat = new File(savePath);
        if (!magnetFilePat.exists()) {
            magnetFilePat.mkdirs();
        }
        SessionManager sessionManager = new SessionManager();
        final CountDownLatch signal = new CountDownLatch(1);


        AlertListener l= new AlertListener() {
            @Override
            public int[] types() {
                return null;
            }

            @Override
            public void alert(Alert<?> alert) {
                AlertType type = alert.type();

                switch (type) {
                    case ADD_TORRENT:
                        System.out.println("Torrent added");
                        ((AddTorrentAlert) alert).handle().resume();
                        break;
                    case BLOCK_FINISHED:
                        BlockFinishedAlert a = (BlockFinishedAlert) alert;
                        TorrentStatus status = a.handle().status();
                        System.out.printf(
                                "进度: %.2f%% | 下载速度: %.2f KB/s | 上传速度: %.2f KB/s | 种子数: %d | Peers数: %d%n",
                                status.progress() * 100,
                                status.downloadRate() / 1024.0,
                                status.uploadRate() / 1024.0,
                                status.numSeeds(),
                                status.numPeers()
                        );
                        break;
                    case TORRENT_FINISHED:
                        System.out.println("Torrent finished");
                        signal.countDown();
                        break;
                }
            }
        };
        sessionManager.addListener(l);
        sessionManager.start();
        // 开启DHT功能
        sessionManager.startDht();
        //设置最大连接数
        sessionManager.maxConnections(200);
        //设置上传速率限制为1024KB/s
        sessionManager.uploadRateLimit(1024);
        //设置下载速率限制为1024*1024KB/s
        sessionManager.downloadRateLimit(1024*1024);

        //sessionManager.download(magnetLink, magnetFilePat, TorrentFlags.SEQUENTIAL_DOWNLOAD);
        if (!magentDataByte.containsKey(magnetLink)) {
            
            byte[] data = sessionManager.fetchMagnet(magnetLink, 30, magnetFilePat);
            if (data == null) {
                return;
            }else {
                magentDataByte.put(magnetLink,data);
            }
        }
        TorrentInfo ti = TorrentInfo.bdecode(magentDataByte.get(magnetLink));
        FileStorage files = ti.files();
        System.out.println("文件列表: ");
        for (int i=0;i<files.numFiles();i++) {
            System.out.println("file: " + files.fileName(i)+"fileSize: "+files.fileSize(i));
        }
        Priority[] priorities =Priority.array(Priority.IGNORE,files.numFiles());
        if (selectDownloadIndex>0&&priorities.length>selectDownloadIndex) {
                priorities[selectDownloadIndex]=Priority.TOP_PRIORITY;
        }else {
            priorities=null;
        }
        //sessionManager.start();
        sessionManager.download(ti, magnetFilePat,null,priorities,null,TorrentFlags.SEQUENTIAL_DOWNLOAD);
        signal.await();
        //sessionManager.removeListener(l);
        sessionManager.stop();

    }
}